/* hc256_test.c
** 
** Copyright (c) 2007, Matt Hamrick, Siobhan Murtagh & Damon Orecks
** All rights reserved.
** 
** Redistribution  and  use  in  source  and  binary  forms,  with  or  without
** modification, are permitted provided that the following conditions are met:
** 
**  * Redistributions of  source code must  retain the above  copyright notice,
**    this list of conditions and the following disclaimer.
** 
**  * Redistributions in binary form must reproduce the above copyright notice,
**    this list of conditions and the following disclaimer in the documentation
**    and/or other materials provided with the distribution.
** 
**  * Neither  the  name  of the  DangerThink  Project  nor  the names  of  its
**    contributors may be used to endorse or promote products derived from this
**    software without specific prior written permission.
** 
** THIS SOFTWARE IS PROVIDED BY  THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY  EXPRESS OR IMPLIED WARRANTIES,  INCLUDING, BUT NOT  LIMITED TO, THE
** IMPLIED WARRANTIES  OF MERCHANTABILITY AND FITNESS FOR  A PARTICULAR PURPOSE
** ARE DISCLAIMED.  IN NO  EVENT SHALL THE  COPYRIGHT OWNER OR  CONTRIBUTORS BE
** LIABLE  FOR  ANY  DIRECT,   INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR
** CONSEQUENTIAL  DAMAGES  (INCLUDING,  BUT  NOT  LIMITED  TO,  PROCUREMENT  OF
** SUBSTITUTE GOODS  OR SERVICES;  LOSS OF USE,  DATA, OR PROFITS;  OR BUSINESS
** INTERRUPTION)  HOWEVER CAUSED  AND ON  ANY THEORY  OF LIABILITY,  WHETHER IN
** CONTRACT,  STRICT LIABILITY,  OR  TORT (INCLUDING  NEGLIGENCE OR  OTHERWISE)
** ARISING IN ANY WAY  OUT OF THE USE OF THIS SOFTWARE,  EVEN IF ADVISED OF THE
** POSSIBILITY OF SUCH DAMAGE.
**
** $Id: hc256_test.c 20 2007-05-12 22:08:36Z matthew.hamrick $
*/

#include "portable.h"
#include <CUnit/CUnit.h>
#include "hc256.h"
#include "hc256_test.h"
hc256 *cipher = NULL;

int hc256_test_init( ) {
  int rv = 0;

  if( DT_E_NOERR != hc256_new( &cipher ) ) {
    rv = -1;
  } else {
    if( NULL == cipher ) {
      rv = -2;
    }
  }

  return( rv );
}

int hc256_test_clean( ) {
  hc256_delete( cipher );
  return( 0 );
}

void hc256_test_vector1( ) {
  DTErr err = DT_E_NOERR;
  char *output = NULL;
  unsigned int bytes_written = 0;
  int compare = 0;

  static char key[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };

  static char iv[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };

  static char expected[] = {
    0x85, 0x89, 0x07, 0x5b, 0x0d, 0xf3, 0xf6, 0xd8,
    0x2f, 0xc0, 0xc5, 0x42, 0x51, 0x79, 0xb6, 0xa6, 
    0x34, 0x65, 0xf0, 0x53, 0xf2, 0x89, 0x1f, 0x80,
    0x8b, 0x24, 0x74, 0x4e, 0x18, 0x48, 0x0b, 0x72, 
    0xec, 0x27, 0x92, 0xcd, 0xbf, 0x4d, 0xcf, 0xeb,
    0x77, 0x69, 0xbf, 0x8d, 0xfa, 0x14, 0xae, 0xe4,
    0x7b, 0x4c, 0x50, 0xe8, 0xea, 0xf3, 0xa9, 0xc8,
    0xf5, 0x06, 0x01, 0x6c, 0x81, 0x69, 0x7e, 0x32 
  };

  do {
    if( NULL == ( output = malloc( 64 ) ) ) {
      break;
    }

    err = hc256_clear( cipher );
    CU_ASSERT( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_key( cipher, key );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_iv( cipher, iv );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_init( cipher );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_keystream( cipher, output, 64, &bytes_written );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_clear( cipher );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    CU_ASSERT_TRUE( 64 == bytes_written );
    if( 64 != bytes_written ) {
      break;
    }

    compare = memcmp( output, expected, 64 );
    CU_ASSERT_TRUE( 0 == compare );
    if( 0 != compare ) {
      break;
    }

    CU_PASS( "hc256 vector1 passed" );
  } while( 0 );

  if( NULL != output ) {
    free( output );
  }
 
}

void hc256_test_vector2( ) {
  DTErr err = DT_E_NOERR;
  char *output = NULL;
  unsigned int bytes_written = 0;
  int compare = 0;

  static char key[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };

  static char iv[] = {
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };

  static char expected[] = {
    0xbf, 0xa2, 0xe2, 0xaf, 0xe9, 0xce, 0x17, 0x4f,
    0x8b, 0x05, 0xc2, 0xfe, 0xb1, 0x8b, 0xb1, 0xd1,
    0xee, 0x42, 0xc0, 0x5f, 0x01, 0x31, 0x2b, 0x71,
    0xc6, 0x1f, 0x50, 0xdd, 0x50, 0x2a, 0x08, 0x0b,
    0xed, 0xfe, 0xc7, 0x06, 0x63, 0x3d, 0x92, 0x41,
    0xa6, 0xda, 0xc4, 0x48, 0xaf, 0x85, 0x61, 0xff,
    0x5e, 0x04, 0x13, 0x5a, 0x94, 0x48, 0xc4, 0x34,
    0x2d, 0xe7, 0xe9, 0xf3, 0x37, 0x52, 0x0b, 0xdf
  };

  do {
    if( NULL == ( output = malloc( 64 ) ) ) {
      break;
    }

    err = hc256_clear( cipher );
    CU_ASSERT( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_key( cipher, key );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_iv( cipher, iv );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_init( cipher );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_keystream( cipher, output, 64, &bytes_written );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_clear( cipher );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    CU_ASSERT_TRUE( 64 == bytes_written );
    if( 64 != bytes_written ) {
      break;
    }

    compare = memcmp( output, expected, 64 );
    CU_ASSERT_TRUE( 0 == compare );
    if( 0 != compare ) {
      break;
    }

    CU_PASS( "hc256 vector2 passed" );
  } while( 0 );

  if( NULL != output ) {
    free( output );
  }
 
}

void hc256_test_vector3( ) {
  DTErr err = DT_E_NOERR;
  char *output = NULL;
  unsigned int bytes_written = 0;
  int compare = 0;

  static char key[] = {
    0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };

  static char iv[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };

  static char expected[] = {
    0xfe, 0x4a, 0x40, 0x1c, 0xed, 0x5f, 0xe2, 0x4f,
    0xd1, 0x9a, 0x8f, 0x95, 0x6f, 0xc0, 0x36, 0xae,
    0x3c, 0x5a, 0xa6, 0x88, 0x23, 0xe2, 0xab, 0xc0,
    0x2f, 0x90, 0xb3, 0xae, 0xa8, 0xd3, 0x0e, 0x42,
    0x59, 0xf0, 0x3a, 0x6c, 0x6e, 0x39, 0xeb, 0x44,
    0x8f, 0x75, 0x79, 0xfb, 0x70, 0x13, 0x7a, 0x5e,
    0x6d, 0x10, 0xb7, 0xd8, 0xad, 0xd0, 0xf7, 0xcd,
    0x72, 0x34, 0x23, 0xda, 0xf5, 0x75, 0xdd, 0xe6,
  };

  do {
    if( NULL == ( output = malloc( 64 ) ) ) {
      break;
    }

    err = hc256_clear( cipher );
    CU_ASSERT( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_key( cipher, key );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_iv( cipher, iv );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_init( cipher );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_keystream( cipher, output, 64, &bytes_written );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_clear( cipher );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    CU_ASSERT_TRUE( 64 == bytes_written );
    if( 64 != bytes_written ) {
      break;
    }

    compare = memcmp( output, expected, 64 );
    CU_ASSERT_TRUE( 0 == compare );
    if( 0 != compare ) {
      break;
    }

    CU_PASS( "hc256 vector3 passed" );
  } while( 0 );

  if( NULL != output ) {
    free( output );
  }
 
}

void hc256_test_vector4( ) {

  uint32_t i,j;
  uint32_t b;

  /* setup keys, ivs and expected outputs */
  static uint8_t key[32] = {
    0x00U, 0x00U, 0x00U, 0x00U,
    0x00U, 0x00U, 0x00U, 0x00U,
    0x00U, 0x00U, 0x00U, 0x00U,
    0x00U, 0x00U, 0x00U, 0x00U,
    0x00U, 0x00U, 0x00U, 0x00U,
    0x00U, 0x00U, 0x00U, 0x00U,
    0x00U, 0x00U, 0x00U, 0x00U,
    0x00U, 0x00U, 0x00U, 0x00U
  };

  static uint8_t iv[32] = {
    0x00U, 0x00U, 0x00U, 0x00U,
    0x00U, 0x00U, 0x00U, 0x00U,
    0x00U, 0x00U, 0x00U, 0x00U,
    0x00U, 0x00U, 0x00U, 0x00U,
    0x00U, 0x00U, 0x00U, 0x00U,
    0x00U, 0x00U, 0x00U, 0x00U,
    0x00U, 0x00U, 0x00U, 0x00U,
    0x00U, 0x00U, 0x00U, 0x00U
  };

  static uint8_t expected[64] = {
    0xC6U, 0xB6U, 0xFBU, 0x99U,
    0xF2U, 0xAEU, 0x14U, 0x40U,
    0xA7U, 0xD4U, 0xCAU, 0x34U,
    0x20U, 0x11U, 0x69U, 0x4EU,
    0x6FU, 0x36U, 0xB4U, 0xBEU,
    0x42U, 0x0DU, 0xB0U, 0x5DU,
    0x47U, 0x45U, 0xFDU, 0x90U,
    0x7CU, 0x63U, 0x06U, 0x95U,
    0x5FU, 0x1DU, 0x7BU, 0xDAU,
    0x13U, 0xAEU, 0x7EU, 0x36U,
    0xAEU, 0xBCU, 0x53U, 0x99U,
    0x73U, 0x3BU, 0x7FU, 0x37U,
    0x95U, 0xF3U, 0x40U, 0x66U,
    0xB6U, 0x01U, 0xD2U, 0x1FU,
    0x2DU, 0x8CU, 0xF8U, 0x30U,
    0xA9U, 0xC0U, 0x89U, 0x37U
  };


  uint8_t actual0[64];
  uint8_t actual1[64];
  uint8_t *actual;
  hc256 context;
  unsigned int bytes_written;

  /* clear the context and the space for the actual results */
  memset( actual0, 0, 64 );
  memset( actual1, 0, 64 );
  memset( & context, 0, sizeof( hc256 ) );

  /* copy the key and iv into the context */
  memcpy( context.key, key, 32 );
  memcpy( context.iv, iv, 32 );

  /* now initialize */
  hc256_init( &context );

  for( i = 0; i < 0x10000; i++ ) {
    if( 0 == ( i & 1 ) ) {
      actual = actual0;
    } else {
      actual = actual1;
    }

    hc256_keystream( &context, (char *) actual, 64, &bytes_written );
    
    if( 0 == ( i & 1 ) ) {
      for( j = 0; j< 64; j++ ) {
	actual0[ j ] = actual0[ j ] ^ actual1[ j ];
      }
    } else {
      for( j = 0; j< 64; j++ ) {
	actual1[ j ] = actual0[ j ] ^ actual1[ j ];
      }
    } 
  }

  /* now check to see if we got the right output */
  b = 0;
  for( i = 0; i < 64; i++ ) {
    if( actual[i] != expected[i] ) {
      b = 1;
      break;
    }
  }
  if( 0 == b ) {
    CU_PASS( "lower vector 1 generated correct results" );
  } else {
    CU_FAIL( "lower vector 1 did not generated correct results" );
  }
}

/* Ensure that we fail with a DT_E_NULL when we call hc256_new() with a 
** NULL pointer.
*/
void hc256_test_new_null( void ) {
  hc256 *cipher = NULL;
  int i,b;
  char *data;
  DTErr err;

  do {

    /* we're expecting this to fail */
    err = hc256_new( NULL );
    CU_ASSERT_EQUAL( DT_E_NULL, err );
    if( DT_E_NULL != err ) break;

    CU_ASSERT_EQUAL( DT_E_NOERR, hc256_new( &cipher ) );
    CU_ASSERT_NOT_EQUAL( NULL, cipher );
  
    if( NULL != cipher ) {
      data = (char *)cipher;
      b = 0;
      for( i=0; i<sizeof(cipher); i++ ) {
	if( 0 != data[i] ) {
	  b = 1;
	  break;
	}
      }
      hc256_delete( cipher );
    
      if( 0 == b ) {
	CU_PASS("cipher was allocated and initialized");
      } else {
	CU_FAIL("cipher was allocated but not initialized.");
      }
    }
  } while( 0 );

}

void hc256_test_new_non_null( void ) {
  hc256 cipher_struct;
  hc256 *cipher;
  char *data;
  DTErr err;
  uint32_t i, b;

  do {
    cipher = &cipher_struct;
    memset( cipher, 0x55, sizeof( hc256 ) );

    err = hc256_new( &cipher );
    CU_ASSERT_EQUAL( DT_E_NOERR, err );
    if( DT_E_NOERR != err ) break;

    b = 0;
    data = (char *) cipher;
    for( i = 0; i < sizeof( hc256 ); i++ ) {
      if( 0 != data[i] ) {
	b = 1;
	break;
      }
    }

    if( 0 == b ) {
      CU_PASS("properly initialized a pre-allocated context.");
    } else {
      CU_FAIL("did not initialize a pre-allocated context.");
    }
    
  } while( 0 );
  
}

/* Test to make sure we really set the key when we call hc256_key()
 */
void hc256_test_key( void ) {
  char in[32] = {
    0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
    0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
    0xA5, 0x5A, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0xFF
  };

  uint32_t key[8] = {
    0x01234567U,
    0x89ABCDEFU,
    0x00112233U,
    0x44556677U,
    0x8899AABBU,
    0xCCDDEEFFU,
    0xA55ADEADU,
    0xBEEF00FFU
  };

  hc256 *cipher = NULL;
  DTErr err;
  uint32_t i, b, *inside;

  do {
    err = hc256_new( &cipher );
    CU_ASSERT_EQUAL( DT_E_NOERR, err );
    if( DT_E_NOERR != err ) break;

    err = hc256_key( cipher, in );
    CU_ASSERT_EQUAL( DT_E_NOERR, err );
    if( DT_E_NOERR != err ) break;

    inside = cipher->key;
    b = 0;
    for( i=0; i<8; i++ ) {
      if( inside[i] != key[i] ) {
	b = 1;
	break;
      }
    }
    
    if( 0 == b ) {
      CU_PASS("propertly setting key.");
    } else {
      CU_FAIL("problems setting key.");
    }
  } while( 0 );

}

/* we're supposed to get a DT_E_NULL when we call hc256_key() with nulls for
** either the context or the key parameters.
*/
void hc256_test_key_null_cipher( void ) {
  hc256 *cipher = NULL;
  DTErr err;
  char key[32] = {
    0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
    0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
    0xA5, 0x5A, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0xFF
  };

  do {
    err = hc256_new( &cipher );
    CU_ASSERT_EQUAL( DT_E_NOERR, err );
    if( DT_E_NOERR != err ) break;

    err = hc256_key( NULL, key );
    CU_ASSERT_EQUAL( DT_E_NULL, err );

    hc256_delete( cipher );
  } while( 0 );

}

void hc256_test_key_null_key( void ) {
  hc256 *cipher = NULL;
  DTErr err;

  do {
    err = hc256_new( &cipher );
    CU_ASSERT_EQUAL( DT_E_NOERR, err );
    if( DT_E_NOERR != err ) break;

    err = hc256_key( cipher, NULL );
    CU_ASSERT_EQUAL( DT_E_NULL, err );

    hc256_delete( cipher );
  } while( 0 );
}

void hc256_test_key_null_cipher_and_key( void ) {
  CU_ASSERT_EQUAL( DT_E_NULL, hc256_key( NULL, NULL ) );
}

void hc256_test_iv( void ) {
  char in[32] = {
    0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
    0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
    0xA5, 0x5A, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0xFF
  };

  uint32_t iv[8] = {
    0x01234567U,
    0x89ABCDEFU,
    0x00112233U,
    0x44556677U,
    0x8899AABBU,
    0xCCDDEEFFU,
    0xA55ADEADU,
    0xBEEF00FFU
  };

  hc256 *cipher = NULL;
  DTErr err;
  uint32_t i, b, *inside;

  do {
    err = hc256_new( &cipher );
    CU_ASSERT_EQUAL( DT_E_NOERR, err );
    if( DT_E_NOERR != err ) break;

    err = hc256_iv( cipher, in );
    CU_ASSERT_EQUAL( DT_E_NOERR, err );
    if( DT_E_NOERR != err ) break;

    inside = cipher->iv;
    b = 0;
    for( i=0; i<8; i++ ) {
      if( inside[i] != iv[i] ) {
	b = 1;
	break;
      }
    }
    
    if( 0 == b ) {
      CU_PASS("propertly setting iv.");
    } else {
      CU_FAIL("problems setting iv.");
    }
  } while( 0 );
}

void hc256_test_iv_null_cipher( void ) {
  char in[32] = {
    0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
    0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
    0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
    0xA5, 0x5A, 0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0xFF
  };

  CU_ASSERT_EQUAL( DT_E_NULL, hc256_iv( NULL, in ) );
}

void hc256_test_iv_null_iv( void ) {
  hc256 *cipher = NULL;
  DTErr err;

  do {
    err = hc256_new( &cipher );
    CU_ASSERT_EQUAL( DT_E_NOERR, err );
    if( DT_E_NOERR != err ) break;

    err = hc256_iv( cipher, NULL );
    CU_ASSERT_EQUAL( DT_E_NULL, err );

    hc256_delete( cipher );
  } while( 0 );
}

void hc256_test_iv_null_cipher_and_iv( void ) {
  CU_ASSERT_EQUAL( DT_E_NULL, hc256_iv( NULL, NULL ) );
}

void hc256_test_initf( void ) {
  hc256 *cipher = NULL;
  static char key[] = {
    0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };

  static char iv[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };
  DTErr err;
  unsigned int *data;
  static unsigned int expected[] = {
  0x00000055U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U,
  0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U,
  0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x27A3297CU, 0xB79D8C05U,
  0x499464CDU, 0xE5B02A56U, 0x487677C4U, 0x5751ED2DU, 0xD0D70B49U, 0xCF489A80U,
  0x65EC6DF2U, 0x01D0C7FDU, 0x35990B58U, 0xAD510037U, 0x7FE981E0U, 0xF8C81D81U,
  0x5E97EFF7U, 0x2A8C1B99U, 0xB2E8D361U, 0x5AC794A5U, 0xED3877DCU, 0xDED4664CU,
  0x629D2859U, 0x27298025U, 0x85E08862U, 0xAD27FF95U, 0xDB52F7E2U, 0x00AED623U,
  0xE8C44118U, 0x98B1B08EU, 0x7B44D894U, 0x51ED69BBU, 0x42C499E1U, 0x787769C8U,
  0xBF670089U, 0x638E366FU, 0xF1EC325DU, 0x57C4F218U, 0x90A9D668U, 0x254E970FU,
  0xF92B6F03U, 0x706073D3U, 0xB350E7F1U, 0xCA0DB623U, 0x742BD771U, 0xD8EA2CB3U,
  0x044A7987U, 0x2504B50CU, 0xD9810287U, 0x2D0D26D7U, 0x1E245AA9U, 0xB12B103DU,
  0x16EE3C08U, 0x80E2FE12U, 0xD209493FU, 0x98D6D0A5U, 0xC491DD72U, 0xEB03377EU,
  0x5E42180DU, 0xDB020104U, 0xDD18732CU, 0x9B4063CCU, 0xD14032A6U, 0x8F4E07C7U,
  0xFB248507U, 0x3DB26BE8U, 0xDAB450D6U, 0xF696EA21U, 0x189BA377U, 0xB8F7B5B2U,
  0x1D4A6D30U, 0xA78B2CC0U, 0x8C539680U, 0xD2783231U, 0x7177A610U, 0x3507870FU,
  0x3035339BU, 0xA7183D2CU, 0x2DB765E4U, 0x24832F4BU, 0xD4557A7CU, 0xFD4D4C01U,
  0x2BD42A82U, 0xCA31B400U, 0xDF54A828U, 0x9073567EU, 0xA3F7B00BU, 0x40245819U,
  0x74BA81CDU, 0xF77648BAU, 0x9ABE34DDU, 0x075974ACU, 0xF6370191U, 0x9DDF3041U,
  0x56196DDFU, 0xE6A9E352U, 0x218203ADU, 0x26D0543FU, 0xCE2C1DC1U, 0x6D81E56DU,
  0x8932C6B5U, 0xBBA9A9DEU, 0x19667AD8U, 0x04352A94U, 0xDC33479EU, 0xA2C923DBU,
  0x8B1A7375U, 0x1C015E0DU, 0xB572D1C3U, 0xD0FA7D3DU, 0xD8C53008U, 0x32758BDBU,
  0x9959DBA5U, 0x9997C76BU, 0x8DCD8DB7U, 0x0E5A8652U, 0x7AD218C1U, 0x4074D34DU,
  0xA698ED69U, 0x9800905EU, 0x55FBB30EU, 0x815BE815U, 0x75E3314AU, 0x73F1F61AU,
  0x495D2CD4U, 0x2CA4288AU, 0x0DC98D85U, 0x8BE242EBU, 0xBCA5FB7AU, 0x7C039E26U,
  0xB87765F3U, 0x4E8F09E4U, 0x0CC3ED55U, 0x53D6CA4BU, 0xF8624CCEU, 0x0655CE42U,
  0x59FEAE5EU, 0xBADBDE50U, 0x2E412CB8U, 0x80180C95U, 0x749A314AU, 0x3A876E15U,
  0x967F71CDU, 0x0BABCADFU, 0xA1C19139U, 0xB23AA6C9U, 0x3B602AD7U, 0xEECF99D4U,
  0x7754B7BDU, 0x62836FBFU, 0x43414B71U, 0x1503B4DAU, 0x313C0C76U, 0xC48CA073U,
  0x217D3AC1U, 0xDFFF611BU, 0xF8279B5EU, 0xC04BD418U, 0x56DD23F6U, 0x08D87CD5U,
  0xDE924A33U, 0x2CBE8F6CU, 0xA07848ACU, 0x673110D7U, 0xF1F41DD0U, 0x3A93B8B0U,
  0xEE901786U, 0xA74C5074U, 0x2F43F9B3U, 0x5FA6D5A9U, 0xC417B7E5U, 0x8F5EA87AU,
  0xE6239423U, 0xCF49C7FBU, 0xEBDB7165U, 0x08167CE8U, 0x222AB8DCU, 0x9439CDC4U,
  0xE6EFA4E9U, 0x2D1C679CU, 0x37CDC062U, 0x7AF7832CU, 0x253ACF85U, 0xD8E3D63AU,
  0x797F96BBU, 0x13F3B7D8U, 0x89E47948U, 0x0173C5CCU, 0xC0AA31F4U, 0x97E7D5A3U,
  0x5B517155U, 0xEEBC27AFU, 0xF212B606U, 0x1DF2D74EU, 0x909E187EU, 0x64A0EB53U,
  0x081E3762U, 0x360CB49CU, 0xAC7AD931U, 0x4B997E82U, 0x0EF8A0A0U, 0xC6483BA2U,
  0x549C8F03U, 0xC70C41EAU, 0x8E89DBE3U, 0x1E865600U, 0x99A08161U, 0x0960E5CBU,
  0xB0A26AEEU, 0xF872683FU, 0x709EB1D9U, 0x33C72E9AU, 0x00B5116FU, 0xB665084CU,
  0xE712BF57U, 0x5D066A88U, 0xF12C4E37U, 0xD2AE84DBU, 0x38780147U, 0xC25EDC70U,
  0x0567CB5EU, 0x4C72F731U, 0xD21E4EA7U, 0xF0846131U, 0x49DBFF11U, 0xC2AD4683U,
  0xC2542A25U, 0x3AACA838U, 0x73DB06F5U, 0x8030214AU, 0xE3F9C87BU, 0x8493360FU,
  0x17AE49CEU, 0xC4A08287U, 0x681D340DU, 0x7F35ADD4U, 0xDE1C893AU, 0x567B5813U,
  0xD83EEB23U, 0x204DF52EU, 0x4A3912E7U, 0x284A1458U, 0xC5A53BB5U, 0x8B2C479AU,
  0xD9112641U, 0xAEDF771EU, 0xAE0ADB15U, 0x0489A51BU, 0x1BB42373U, 0x6F64FC7EU,
  0x8902930BU, 0x88BB1BCEU, 0x16FE3F95U, 0x5AC2451AU, 0x54824B65U, 0x0D091A85U,
  0x931BF6F0U, 0xE2618374U, 0xB36A3578U, 0x46AD03BDU, 0x25929EFBU, 0x9A2B32AEU,
  0x78311553U, 0x1937967BU, 0x1B3E286BU, 0x8D54A6A5U, 0x29C74C9AU, 0xB932F144U,
  0x13030325U, 0x4A93A15EU, 0x0F1F2120U, 0xD1B5F507U, 0x04EB7442U, 0x5DD2FC7DU,
  0xAF1CAF96U, 0x434CCB10U, 0xF76508B2U, 0x712756A3U, 0x46C338FFU, 0x0EC6E2F8U,
  0x983AB6BBU, 0xCF1A652CU, 0x4AE687EFU, 0x6717EFB0U, 0xAB9ECB41U, 0x8F3F67BFU,
  0x23A807ABU, 0x6548459AU, 0xB9DD8D31U, 0x4B590677U, 0x9A6653BAU, 0x388F8473U,
  0x6CEE133AU, 0x58C7E9D8U, 0x26832F26U, 0xA7AF08F9U, 0xFCA13A38U, 0x98BE48CAU,
  0x516F1F41U, 0xA0F102F5U, 0xDFD5A490U, 0x8F49317DU, 0x375D1BADU, 0xEB8D2BA9U,
  0x19ADDA29U, 0x1DE75612U, 0xDEB75B1DU, 0xE1CE6189U, 0x86521C37U, 0x394B5068U,
  0x6C4BF3B0U, 0x9E8CEB41U, 0x2E4A62A0U, 0x48E7A417U, 0x0A861AC0U, 0xBB0A6D8AU,
  0x64B4338EU, 0x30B44626U, 0x1D7583E2U, 0x64FCB98CU, 0x15029816U, 0xE6F8205FU,
  0x9C1C7008U, 0x4E32A7F8U, 0x1B10BBF8U, 0xC6884436U, 0xED7757F8U, 0x82CFA991U,
  0xF9281838U, 0xF7635E72U, 0x53EFADABU, 0x21CAE12CU, 0x6D664877U, 0x495519F6U,
  0x52775796U, 0xF3104191U, 0x58729A1DU, 0x880AB310U, 0xF8A6515FU, 0x3C46F95FU,
  0x7DCAEC43U, 0x4996FCD2U, 0x92589015U, 0xF89EF8D6U, 0x2B3164F7U, 0x4C84011FU,
  0xD434577EU, 0x2A2C1799U, 0xC2AA9A16U, 0x24046AEBU, 0x88790F58U, 0xB2CE27A8U,
  0xC019B56FU, 0xADDB5F46U, 0xECBD46B1U, 0xF141334DU, 0x487A3C20U, 0xE11F1006U,
  0x51F4FD51U, 0xAA025780U, 0x9AF7C55FU, 0x5B56E24AU, 0x1E5E2A1AU, 0x16E2E39BU,
  0x17E40BC9U, 0x32616B41U, 0x94A81D84U, 0x79F48211U, 0xB395F20DU, 0xE55A3758U,
  0xCAB74432U, 0x8B2DBCE2U, 0xD69FD919U, 0x917F557AU, 0xF58EACC6U, 0x5D356684U,
  0xE58F9ED3U, 0xF8A1110EU, 0x9EE91A55U, 0xD2A41DCCU, 0x1A1BE59BU, 0x4DA98DA9U,
  0xE8E2EF49U, 0xEE2B878DU, 0xD601E405U, 0x6AF6E1CBU, 0x5389A3B2U, 0xD43D5D3BU,
  0xEBB5BA97U, 0xDB339B2AU, 0x51D8F789U, 0x5F3E3562U, 0xDE33154FU, 0x03B513F5U,
  0x87D11912U, 0x4A1B2FAAU, 0x6598A038U, 0x3DA6EBAAU, 0xEC8858D5U, 0xC748DE0BU,
  0xE67A46A0U, 0x05D9BF41U, 0xF54E514DU, 0x6FBCD53AU, 0xF21A72AEU, 0xA7D2342EU,
  0xB4123FC8U, 0xE0CC6D32U, 0x98965BABU, 0xAE6855B0U, 0x64110D99U, 0xB55E4489U,
  0xDD213C55U, 0x82C1C287U, 0x25108C49U, 0x8D2795C4U, 0xDB37F1DBU, 0x479D23BAU,
  0x3BEF3CD6U, 0xEC91A6A9U, 0xA60F3871U, 0xACDA4ACCU, 0x8167B3CEU, 0x82F10937U,
  0xF232BEC7U, 0xD035BC77U, 0x2EF595D7U, 0x65F598F8U, 0xA7DAF751U, 0x471C308FU,
  0x59463C1BU, 0xFE7D5198U, 0xD8CDDAD5U, 0xA65BF72CU, 0x0D5A84A7U, 0xBDEBE4B7U,
  0x15DF4210U, 0xAEE49DAAU, 0x5D41D1A7U, 0x0178498AU, 0x62261252U, 0x18B5C4B3U,
  0xD0105021U, 0x15C9C961U, 0xBE909A32U, 0x1A494695U, 0xD2454419U, 0x3F9F6E91U,
  0xA012E96FU, 0x702FCDCAU, 0x03701E3EU, 0xFBC5C5B0U, 0xA95596F2U, 0x3BB04321U,
  0x22D4C518U, 0x473B7F66U, 0x01472D96U, 0x841A193FU, 0xACFE0799U, 0xA9FBF732U,
  0xE151F561U, 0x682F0186U, 0x4C4496DDU, 0x84365652U, 0x24FFC0C8U, 0xAED58D84U,
  0x6ECCA5C5U, 0x763FA832U, 0xEA78A47FU, 0x87F7E764U, 0x55E17B2EU, 0x963DF6F0U,
  0xD109DCECU, 0x88121342U, 0x8DF16A55U, 0x4D07336EU, 0x74CA4D8FU, 0x85B946C9U,
  0x13BC51FEU, 0xF5800A54U, 0xD2A6F5BFU, 0x300A2C61U, 0xE2737237U, 0x7ED5E6D7U,
  0x54BBAF11U, 0x81B1B723U, 0xB25E101CU, 0x823EB179U, 0x6D6F3DC1U, 0xA4405DD4U,
  0x96DD5A03U, 0xA5452267U, 0x91DBE422U, 0x32000FCAU, 0xF0D6BFF1U, 0x51C1F2B1U,
  0xECACB205U, 0x0D543A64U, 0x4C694877U, 0x03753901U, 0xBE367DEFU, 0x679DD9A2U,
  0xA02EBDABU, 0x05D1851AU, 0x937FEB4AU, 0x7D10F089U, 0xEBE22504U, 0x971D631FU,
  0x48C40472U, 0xCDAEA26FU, 0xFDB59438U, 0xD2E30E42U, 0x17AEE8E4U, 0x659B3D61U,
  0x9E67C88FU, 0x27B4BEBDU, 0x9D1E69CEU, 0xAFC663C3U, 0x1EC67B44U, 0x472A2525U,
  0x3A7F9FFCU, 0x4DC5D4A4U, 0xAE626248U, 0x020396A7U, 0xA87AC935U, 0xEA5C69D1U,
  0xA23976EFU, 0x7F14D8C8U, 0x43A12DEAU, 0x667F4149U, 0x8FDDA27EU, 0x7DB9592EU,
  0x9B8E296EU, 0xA5529235U, 0xBF1FEE21U, 0xB56E76B4U, 0x1EE2CC10U, 0x9EBEEA57U,
  0x0152E44DU, 0x25DF95C1U, 0x6740F4BDU, 0x7377AFC8U, 0x91BE77CFU, 0xA92E55CAU,
  0x72876959U, 0xE736C59EU, 0x6E6E6C87U, 0x3774C3E3U, 0x15254F89U, 0x7E37E654U,
  0xDBB690CEU, 0x2C5F9426U, 0xDB882840U, 0x4BC134FCU, 0x0C1F51B4U, 0x05CDAA6CU,
  0x3B34841BU, 0x2B3736D9U, 0x07112F23U, 0xB7C0E76CU, 0x9FAFCBD5U, 0xBCEBFE59U,
  0x3371BCD5U, 0xA50A4573U, 0x377B5100U, 0x142F91C3U, 0x57539AE0U, 0x9BCD4022U,
  0x9D3C20DFU, 0x0220F0F2U, 0xBC1A2069U, 0xA4C720EAU, 0xE531CC22U, 0xB08AB702U,
  0x80A14E9DU, 0xC4E3EB5EU, 0x96A6A793U, 0x9541527AU, 0xC0055CAEU, 0x5D62211AU,
  0x013121ECU, 0x4C99E1F8U, 0x81B4998EU, 0xA64D6187U, 0xC4F944B0U, 0x58286057U,
  0x8376AC25U, 0xDDB696FDU, 0x167A94A8U, 0x6FE05F75U, 0xD5276E75U, 0x1EA11001U,
  0x5232345FU, 0xA928B00EU, 0x3C43686FU, 0x8D7DBDDCU, 0xC62C92CDU, 0xC0DDE1B8U,
  0x1B8F1024U, 0x5091DF49U, 0xA7ACEE23U, 0x15E070F0U, 0x605F946EU, 0x02C07A05U,
  0xFBC46054U, 0x2DA20C25U, 0xFBF0F9B9U, 0x341B2008U, 0x95F6026AU, 0x81E3B84DU,
  0x6E946ABCU, 0x97AB9085U, 0xF1FD7A0AU, 0x94ED7230U, 0x44D08E95U, 0xBD4B2715U,
  0x4EAC7B27U, 0x812C2A75U, 0x5F738C71U, 0xD1767656U, 0x64EB1B74U, 0xF436D9A8U,
  0x871A9263U, 0xFA30FE45U, 0xDBAF369DU, 0xEDF1A546U, 0xDEEF8C53U, 0x5617FDEBU,
  0x6D572661U, 0x715E4E39U, 0x470A2DA4U, 0xDB238EC5U, 0x21064236U, 0xC4E58EA5U,
  0x3B20FE9BU, 0x74318D66U, 0x9C10B6C1U, 0x9F2BFA16U, 0xADCD5381U, 0xD7E55D44U,
  0xC1EB4B8FU, 0x106EC7BAU, 0xFA9345F8U, 0xD773A713U, 0xA4FE556DU, 0xCD0FE924U,
  0x54C594F0U, 0xDAEA5679U, 0x29C1A30EU, 0x48B144ACU, 0x31216B39U, 0x9A11A142U,
  0x07D586A4U, 0x2DD46526U, 0xA79F2C47U, 0xF4FFF174U, 0xB730B899U, 0x657BEC6CU,
  0x7319DFAEU, 0x7403A158U, 0xE9F12ACBU, 0x21FBE41BU, 0x1E3BFC9CU, 0x37F19B4BU,
  0xB8D3CC98U, 0x3FA2BEC5U, 0x0D26A6F1U, 0x3919A270U, 0x5245A4ACU, 0xB81ED136U,
  0x856E2E9BU, 0xDBEE5221U, 0x928C6DACU, 0x6EAEC069U, 0x188F922FU, 0x61F7D5AAU,
  0x2D278324U, 0xE5467937U, 0xABC30823U, 0xE7AEC34DU, 0xFC592921U, 0x7B243233U,
  0x7C69BC04U, 0x0B8E506FU, 0xE99DD004U, 0xEE7CC009U, 0x6F415CA5U, 0x1C8F27D4U,
  0xC32E9C34U, 0xB7632CC2U, 0xE1EC22E4U, 0x287F4E38U, 0x54F45B52U, 0x74812161U,
  0x41704574U, 0xA8B949B7U, 0x030A37EEU, 0x8124387DU, 0xEB0E0162U, 0x724D00E7U,
  0x077E234BU, 0x67E9725AU, 0xCCA05228U, 0x5A4524FEU, 0x3CFAB30AU, 0x64574964U,
  0x51D374EAU, 0xB4F595A2U, 0x766EDD42U, 0xA03A09B0U, 0x5597D5F6U, 0x36F5F1D0U,
  0x22E8AB9AU, 0xC4F28465U, 0x9AEFB620U, 0x729BF8A4U, 0xD32F495AU, 0x148FC0C1U,
  0xA4FED171U, 0xE14805B7U, 0xCAD77681U, 0x08ADB0D9U, 0x00A8A79DU, 0x101C58BFU,
  0xA8D8C204U, 0x4185756AU, 0xF4EAEEFDU, 0xA9CFC6D0U, 0x9304E0DEU, 0x458E0E8AU,
  0xBE50442BU, 0xACA6FEF4U, 0xAAD2C0F5U, 0xE183E06FU, 0x3AEDA36BU, 0x7D955A75U,
  0xC4120FC0U, 0x2520A390U, 0xDC34F33BU, 0xE7506997U, 0x910B9146U, 0xF0866603U,
  0x96842118U, 0x1815730FU, 0xD81A6EA7U, 0x28841468U, 0xAFAF6CD8U, 0x010D1783U,
  0x0D08D895U, 0xD35D00C3U, 0x7AEE11F7U, 0x8C949200U, 0xB8A38364U, 0x76219CB1U,
  0x96D07996U, 0xF8E37F8BU, 0xC5B1D136U, 0x36DDC2CCU, 0x9D468151U, 0x28BB971CU,
  0x3E2AAF8EU, 0x969B053DU, 0xF2195D71U, 0x0A9CB232U, 0x78036C1DU, 0x05E7556DU,
  0xA2065871U, 0xC720555AU, 0xC5F2F934U, 0xFFD01E63U, 0xE4FD5330U, 0x0B8A7415U,
  0xF75865F9U, 0x76F62F23U, 0x6EAA4C09U, 0xEA900D88U, 0x98C04E83U, 0x6F77222EU,
  0x90AAB509U, 0xDA9752EBU, 0x42FBC042U, 0xA9B54402U, 0x926D1839U, 0x6273950BU,
  0x1B900028U, 0x870246C6U, 0x64C26E96U, 0x49BBDAA6U, 0xDC318DB3U, 0xEEF8B4AFU,
  0xCF0DE573U, 0x259FD344U, 0x8EBE4FBBU, 0xDCFADA97U, 0x5E971306U, 0xAAE4E369U,
  0xEEE1D4CCU, 0x2D4E056DU, 0xF88F88BFU, 0x529D0F66U, 0x2B75FA07U, 0x37BD24CFU,
  0xF9E6082DU, 0xA42F853BU, 0x3FEE548DU, 0x19FAC828U, 0xCD85592FU, 0xBD73F7B8U,
  0x9E2B2140U, 0x1B6ABB9CU, 0x831076BDU, 0x4EDE0724U, 0x3E8BC5FCU, 0x1754B683U,
  0xF49DEFAFU, 0xCB53169AU, 0x004E7464U, 0xBFC0D94CU, 0x5FA4E961U, 0x049D86CCU,
  0x703B786DU, 0x5F67A53FU, 0xFE6F3A2FU, 0xA7AC46D1U, 0x8EB280D4U, 0xD4F7BE57U,
  0x74755C0FU, 0x4D821E9EU, 0x47C4C26DU, 0x00D45442U, 0xDCA2FDFEU, 0x917BD37DU,
  0x5E859935U, 0xD5019A94U, 0x822AC1EEU, 0x9609A744U, 0xB7BBDE96U, 0xFB3BB3D5U,
  0xF408195BU, 0xFF4E8EDFU, 0xA7A21AC2U, 0x2624F68DU, 0xB081B405U, 0xBA26219BU,
  0x8C6BAFDFU, 0xDCE39F87U, 0x1FAFA413U, 0x208FA963U, 0x73CAA3E0U, 0xB61B14E1U,
  0x2BC93D84U, 0xFF761E4EU, 0xCB9CB13EU, 0xC34FC2A3U, 0x71D1B9FDU, 0xFF9673D9U,
  0x979AA555U, 0x08BD3B49U, 0x6FCBE433U, 0xAF15E97CU, 0x69955163U, 0x1626FB31U,
  0x843A252FU, 0xBC93D221U, 0xF337E4C7U, 0x35D94BCDU, 0x8DDD725AU, 0xFA20ABC2U,
  0xA8B2FFD4U, 0xE1C88FA4U, 0xEAC56480U, 0x3CD85338U, 0xCC631588U, 0x09B1D564U,
  0x7A4EAB69U, 0xDF9354A0U, 0x3A18C46DU, 0xD46D3F3CU, 0xE8751756U, 0xF985166AU,
  0x34EA6ECFU, 0x3CC7F8A2U, 0xE7BF9EECU, 0xA29F8E2EU, 0x916D419DU, 0xDA7B5C8BU,
  0x75D3DB6DU, 0x9AA7B7CDU, 0x3046FB96U, 0xB66FC3B7U, 0x2E6030DAU, 0xD0DE8D15U,
  0x87A53BEEU, 0x3837588BU, 0xD4006548U, 0x800EF787U, 0xB9C3B521U, 0xC3C38964U,
  0x77A9A451U, 0x316129E2U, 0xC1E376F2U, 0x00D86B8FU, 0x1D702CA6U, 0x44B3CA5EU,
  0x4C0BE8D2U, 0xE6C89B5AU, 0xB95E62E4U, 0x14D26BE2U, 0x12632607U, 0xC9BE687BU,
  0xCC225A13U, 0xCC13BF7DU, 0x5553945BU, 0x5D309E4EU, 0xED77BE3CU, 0xCB67E976U,
  0x53EF974FU, 0x73328623U, 0xCB7E78E9U, 0x143BEE92U, 0xF38C2CF2U, 0xD158CEDCU,
  0xE75334B0U, 0xF2E356FCU, 0xACC298BCU, 0xBC92057EU, 0x8479BF20U, 0x52B7EBE4U,
  0x819561F3U, 0xF2862DF2U, 0x5127EABAU, 0x0C1A6595U, 0x83A17F66U, 0xD14068EFU,
  0x7770EB34U, 0xCA6C7051U, 0x08BCE5C2U, 0xE5C42B71U, 0x8CDF5659U, 0x42DA63D2U,
  0x5972E94BU, 0x911E242AU, 0xEB3A4EFAU, 0x148A9601U, 0x9E088318U, 0x45929254U,
  0x84AD0DEDU, 0xEF373AB4U, 0xFF9BAEE9U, 0x5376C934U, 0x21EB63C7U, 0xCF6B78BAU,
  0x21DB582EU, 0x6CDB68ABU, 0x156D2AF6U, 0x2818C2EAU, 0x0151E0FEU, 0xA28E21BFU,
  0x39BB11F3U, 0x6FB8BFA6U, 0x846F347EU, 0xFB0103E5U, 0xF8996BE3U, 0xD7637AF1U,
  0xDE77EB7FU, 0x51356D76U, 0x23597307U, 0x9FF78A65U, 0x13E3E749U, 0xD354DBAEU,
  0x069C038EU, 0x3B8D6AF1U, 0x85DFA03DU, 0x60BA6DE6U, 0x9D9B1C63U, 0xCFBE6C37U,
  0xEB1DC5D1U, 0xD6467A72U, 0x2FB2209CU, 0xBB5A8280U, 0x26E680A1U, 0x5F3B77FEU,
  0x15504067U, 0x355D2E48U, 0xF1F78905U, 0x4C577B51U, 0xBF3A1CBCU, 0x1E0A6CC0U,
  0x83774593U, 0xE1D907FDU, 0x0663AE68U, 0xD86A6ACBU, 0xC80DA5A2U, 0xE11C74BBU,
  0xE6F93ADDU, 0xED68C59CU, 0x8F51C2EFU, 0x8D5E74AEU, 0x1758DDD5U, 0x9EC23BC6U,
  0x32C5309BU, 0x2A0902ADU, 0xF089A322U, 0x7474C1BBU, 0x8E3BB5BFU, 0x1C30B676U,
  0xD1844C3EU, 0xE2293CD0U, 0x1B0EAD95U, 0x605075C2U, 0x78A3FB5DU, 0xF1F0056EU,
  0x3FC0DD23U, 0xD968EA26U, 0xEA32D25BU, 0x1E333B7EU, 0x0E42E324U, 0xE3447894U,
  0x7AC48DF1U, 0x0FD0EE3BU, 0x644F7D74U, 0x371B44F1U, 0x602D697FU, 0x42B66FA6U,
  0xE98A3D8EU, 0x50C15313U, 0xB9050E81U, 0x44CA28EFU, 0x132F0BE5U, 0x2EE79CDCU,
  0xA4C5EA2BU, 0x95D93F9DU, 0x819040A6U, 0x5D106B02U, 0xD6849B09U, 0x52257DC5U,
  0x74053CBCU, 0x055F2B0EU, 0x86600B09U, 0x239406B9U, 0xD0466CECU, 0x2B815BCCU,
  0xA2CD5DFAU, 0x3FA64700U, 0xE74F29ACU, 0x7124E2D6U, 0x2D98E18DU, 0xB7BB40E8U,
  0x19B3B8B0U, 0x3F339CC7U, 0xD36AF186U, 0x36133B6EU, 0xF029E3A9U, 0x5AD81035U,
  0xC51B0A07U, 0x1429BBA8U, 0x1FC0AEBFU, 0x00B57114U, 0x45A29270U, 0xBF1200DBU,
  0xCA0413F3U, 0xF6C40577U, 0x4A7B0E75U, 0x0A2A0D80U, 0x40114121U, 0x0DF33232U,
  0xCBC9C662U, 0xE445A4FCU, 0x3C1D108AU, 0xB80BF87BU, 0x80BF9112U, 0x415B0779U,
  0xCF625C76U, 0x4583BB96U, 0x939CCD8BU, 0xB4E7891DU, 0xA0F8093EU, 0x9FB84ECBU,
  0xF92CD5B6U, 0xC5202E71U, 0x78F651F9U, 0xBD1E093DU, 0x81830C8BU, 0x46BB84D8U,
  0x47E254C9U, 0xA527194EU, 0xE5188132U, 0xF03A9037U, 0xE093104AU, 0xD5994DCFU,
  0x295177C8U, 0xFFC29DDCU, 0xFA23DBCCU, 0x6530C82CU, 0xE0815D99U, 0x12DF41D1U,
  0x5871E1DDU, 0xBA65E5E0U, 0x98741A4BU, 0xCED29A85U, 0x177E1821U, 0x9908BD91U,
  0xD8D8A3B4U, 0x40813961U, 0xEEC1831DU, 0x7551C98CU, 0xE42B0A1BU, 0x58C8BB40U,
  0xDDAF738AU, 0x30AA92FEU, 0xF7875CD0U, 0x2053E815U, 0xC997B128U, 0x06C8C792U,
  0x904206C5U, 0x886EC79BU, 0x07792CE0U, 0x521D23C8U, 0xC709D802U, 0x9FD533D0U,
  0x7F7AC601U, 0x2B059F4DU, 0x367AAE55U, 0x1A1F436BU, 0x6797239FU, 0x58C858FEU,
  0x139E85E2U, 0x44DDDEF9U, 0xA52FC366U, 0xD00CCFA6U, 0xB3D279A1U, 0xE7A12D2DU,
  0x30F0FC25U, 0x7D5BD2BEU, 0xE2EC30A2U, 0x9494337CU, 0xA5ADE32CU, 0xEE0EBA3FU,
  0x6BC7A8D7U, 0x71730F5DU, 0xA54A23B6U, 0x7A11F6ECU, 0x2AADD500U, 0x43306E91U,
  0x4CF801E7U, 0x459F9F3AU, 0xE2F162E6U, 0xB83EC23EU, 0x7CC21F85U, 0x428E462FU,
  0x1711AE9AU, 0xF7F060A6U, 0x72912B7CU, 0x3CC20866U, 0xA2BB4119U, 0x7330B855U,
  0xA63DD84FU, 0xC8F83D38U, 0x236955BCU, 0x790B35EFU, 0x4DF65EC4U, 0xCD317D77U,
  0x284381B5U, 0x39753F29U, 0xEEF6FB52U, 0xFDA4AABDU, 0xA39BAE1FU, 0x8594C978U,
  0xBBF881C5U, 0x8F16A35FU, 0x8B4AE383U, 0x2D0FAF49U, 0x481ABA41U, 0xD8D0208EU,
  0xD3247C3CU, 0x72A6B842U, 0x3FEC3E35U, 0x959954C7U, 0x61EC80C0U, 0xCB727D33U,
  0xABA5F6B3U, 0x840F55B6U, 0xA77AC273U, 0x3667D089U, 0x303647ACU, 0x22BFF6DEU,
  0x05A9426BU, 0x9D2BDF12U, 0x03931024U, 0x7420BBFCU, 0xCCE88B6AU, 0x1E4AA2B0U,
  0x32164EA8U, 0x50863472U, 0x0FB2BDE6U, 0x32C613A5U, 0xBB36D30BU, 0x1CC1B9C2U,
  0x7D021B23U, 0x70254D12U, 0x9AEE589AU, 0xCB64F699U, 0x3B61F0BBU, 0xA0BD7506U,
  0x252840B8U, 0x7382BC64U, 0x89BC01A3U, 0x7ADAC488U, 0xFE34732CU, 0xAEEF85CEU,
  0xCB02C4B4U, 0xB691B68CU, 0x713E4C67U, 0x72DF7B70U, 0x7487C175U, 0x55FA973EU,
  0x147017B4U, 0xB6D95D21U, 0x02C0A38BU, 0x2A07C5BDU, 0x89795992U, 0x42462AB1U,
  0xFBD03A44U, 0x91306C6BU, 0x648010A1U, 0xC5E1AA6BU, 0x7349AB42U, 0x88A34893U,
  0x919C7501U, 0x96CF3392U, 0x870D9BD8U, 0x56D85495U, 0x1C7C8263U, 0x3C246073U,
  0x78579FACU, 0x8E50B7B5U, 0x0C087662U, 0x9C54B5EDU, 0x545C1BB1U, 0x48CA139EU,
  0xE98E33BEU, 0x3B138C9FU, 0x39A96A15U, 0x012EFB23U, 0x0124620EU, 0x82652392U,
  0xC0F02A21U, 0x2C492AFCU, 0x23D04673U, 0x5D228C16U, 0x91B69B07U, 0x32964A1BU,
  0x084861B9U, 0x26EAC9C8U, 0x0C532215U, 0x3D7CFA4BU, 0x139CAC59U, 0x99724E93U,
  0x976172C2U, 0xB9F02019U, 0xC4C8E502U, 0x190A62F1U, 0xA9E8AD25U, 0x8E6DBB52U,
  0x4733C49BU, 0x6A2C3268U, 0x9EDE8577U, 0x2618F183U, 0xC480C45AU, 0x958DD2C3U,
  0x5991AFC1U, 0x4CD68575U, 0x0CF09CDAU, 0xAE5281F5U, 0x776AE53DU, 0xE068231CU,
  0x1A49B847U, 0x6B8B640CU, 0x1767758FU, 0x8679DA28U, 0xDBC6D78CU, 0x73754255U,
  0xF4BB5740U, 0x759C2818U, 0xCACF6D0EU, 0xD4290414U, 0xB3C9CE1AU, 0xD57ADB23U,
  0x25D36608U, 0x38DDDCC4U, 0x74AFF61AU, 0x23BB6D4BU, 0x97E55404U, 0x2C057A47U,
  0x819C62E7U, 0x5C7629A3U, 0x8A9023FEU, 0x17D12CD5U, 0x0DB974FEU, 0xD0EA7A48U,
  0x4F18F3F5U, 0x9D1ECBF9U, 0xD015E36BU, 0x6FEA275DU, 0x50E9B96EU, 0xEAF67F3DU,
  0x3422264CU, 0x193EB78EU, 0xC63B4B29U, 0x0F3BBE2CU, 0x25B141C6U, 0x0D86781FU,
  0x439542FEU, 0x7C00D745U, 0x4D9C63E1U, 0x3846AA49U, 0xD2DDDF9DU, 0x51B6E245U,
  0x6439C592U, 0xFFAF0FAEU, 0x1FABD7C0U, 0x70D07ACEU, 0x99432269U, 0xE52032BAU,
  0x90E052C6U, 0x34B0DED0U, 0x9CA0F473U, 0xF3E7A2FEU, 0x7232012DU, 0xDA2B9E98U,
  0xD3518AB9U, 0xBCA50FD2U, 0x2BA64F11U, 0x6B52B3D9U, 0x4E693397U, 0x8887FE35U,
  0x7DFD615CU, 0x6244B90BU, 0xD0F7269DU, 0xBE78B60BU, 0x1C1484B3U, 0x0B58B4BEU,
  0x15DC90DCU, 0xAC757419U, 0x470A20D9U, 0x4955326BU, 0x5545EFE8U, 0x3DE95EABU,
  0x89F71721U, 0x55762D9EU, 0xDA7FE871U, 0xE6FBB212U, 0x25EA032AU, 0xBAE2A7D1U,
  0x12E4EE82U, 0xEA64018AU, 0xBE5BAA6CU, 0x9D95E907U, 0x994F852FU, 0x093AC0E1U,
  0xA8166EADU, 0x3286D37FU, 0x937B5497U, 0x46C5D1F3U, 0x72E66869U, 0xB85211C6U,
  0xB1C46B35U, 0x157217A9U, 0x9E4AD00CU, 0xD78E826DU, 0x0DAD2D9EU, 0x4E1282CDU,
  0xA22BD970U, 0xBBB7F951U, 0xC358865FU, 0xA46CC331U, 0x7F4E139CU, 0xAB87DF1CU,
  0x6D916725U, 0x929442EDU, 0xE7E616AAU, 0x0AE06DC0U, 0xB8AB2F0BU, 0x6A7B5223U,
  0x471DF338U, 0x81FD13E7U, 0x579383DFU, 0x17155A01U, 0xC6711BB8U, 0x1579737FU,
  0x1D963A12U, 0x6AF520F9U, 0xAEC7E63EU, 0x5EC83022U, 0x8279281DU, 0x56D650A6U,
  0x3BD43C81U, 0x7AE09AA0U, 0xF5B6CED0U, 0x8436A0E6U, 0x2B8A750EU, 0xF938527BU,
  0x1BD759A4U, 0xBB12075DU, 0xF33E4BEEU, 0x628A89A4U, 0xAEB7D987U, 0x8B441181U,
  0xBE93CADDU, 0xE74828F4U, 0xA2EB71FBU, 0xD3DDA851U, 0x25FABCC1U, 0xA26C2A6CU,
  0xEF95CBA2U, 0xF9ECCCC4U, 0xB8AF332DU, 0x173BDB6AU, 0x0A065AD1U, 0x2B137113U,
  0x15FB6955U, 0x1B05F278U, 0x8A18D037U, 0x723C9073U, 0xA62D9B54U, 0x4478CBC7U,
  0x20963A25U, 0x41ECCEFFU, 0x0CB09543U, 0xE6D6119CU, 0x23F11F06U, 0x4CB89E23U,
  0x727E0A0BU, 0x15634BA1U, 0x1A2CF968U, 0x470418F8U, 0x649FAC10U, 0xB088D309U,
  0x40F9548FU, 0xBF84967EU, 0xC849CF05U, 0x0677CF81U, 0xAE015D93U, 0x7134B860U,
  0x3D58418FU, 0xD9AB9C69U, 0x430EE61DU, 0xC537CAE6U, 0x640C8941U, 0x94B7564EU,
  0xE2AF221EU, 0xBE6EADDCU, 0xB13A3ADDU, 0xB6FD0CE8U, 0x0D385D7EU, 0x4C28ECBCU,
  0x0961F8F0U, 0x2C050909U, 0xB452DD2FU, 0x0CC60972U, 0x7998AEF3U, 0x32F55D18U,
  0xA684FC90U, 0xC22F12D0U, 0x02B44C36U, 0x6586BC1BU, 0xFD7AFE7EU, 0x11E6ACEEU,
  0xC90E8824U, 0x6CDF77E5U, 0x1CB24614U, 0xFC2C3208U, 0x84E740D2U, 0x4D01DBFCU,
  0x033F2861U, 0x10BC9ACFU, 0xE0DA46C3U, 0xC94BA5C5U, 0x15E770B1U, 0xD0FCFD55U,
  0xFA5F2D5FU, 0x43D8B4C6U, 0x384D68A0U, 0xFB3C7CBDU, 0xD9671D70U, 0xDBE88547U,
  0x0087859DU, 0xFF56284DU, 0xEDB81BFAU, 0x310CE2B6U, 0x06B8B16DU, 0x9DECD299U,
  0xF54533C3U, 0xBC719F25U, 0x2E930942U, 0xAB12978DU, 0xB636A56EU, 0x50C4C9E3U,
  0x6D7BE87AU, 0xD0AF2144U, 0xC3D7A38AU, 0xBCF32115U, 0xE696471EU, 0xEB179219U,
  0xFD729605U, 0x440D69F1U, 0x6FB7C527U, 0x5E03FB8BU, 0xA2E774E8U, 0xAE5CE9C5U,
  0x2E3C503EU, 0x4155FF62U, 0x20751669U, 0x73BF3A23U, 0xAB378055U, 0x8101CD3AU,
  0x7158FA34U, 0xB82F513AU, 0x798C3EB1U, 0xB4FE0E68U, 0xFD1D0ACDU, 0xAA9C50A1U,
  0xDA51CF0AU, 0x30A4ED65U, 0x281BDEBCU, 0xC27DF1EAU, 0x5A9984DAU, 0xD8C017E1U,
  0x8A1839EBU, 0xC9DB46D2U, 0x6C955BDDU, 0x25BCD547U, 0x443981D2U, 0xEEF8F53FU,
  0x9B4A25C1U, 0xED9FD434U, 0x5DA6BB77U, 0xE2F8E353U, 0x2DA635D9U, 0x22B6EBB8U,
  0x78FF0484U, 0xC4521DEFU, 0x829D3E60U, 0xACD03EB5U, 0x99F372B0U, 0xF87B3A44U,
  0xF5F1FE35U, 0x07CEA9E0U, 0x014F7ED4U, 0xE086A0A4U, 0x97086E5FU, 0x08B05CFFU,
  0x8919CA44U, 0x90AAF16BU, 0x7A7B22A2U, 0xC07637C2U, 0x1ED49ED3U, 0x3BA1B35DU,
  0xADD6363EU, 0xA5B94D55U, 0xD3778CC7U, 0xC864C40DU, 0xC137DF16U, 0x024448A8U,
  0xFC4AA136U, 0xB22FEB62U, 0x63344971U, 0x1092DABBU, 0x2B9062E9U, 0xFAEC4BADU,
  0xA8A04A80U, 0x32290B46U, 0xE731007DU, 0xAA680D8EU, 0xFD1EAEC8U, 0x12980F37U,
  0xEC33E135U, 0xDE8EC802U, 0x2BAA2A1CU, 0x98E20FA1U, 0xB3307776U, 0x4544AC64U,
  0xE6A6BFC5U, 0x59E2EF52U, 0x88053BAEU, 0x6F224625U, 0xBB68460DU, 0x9FE2BBE0U,
  0xB8E9540BU, 0xA7874B76U, 0x0442584DU, 0xA290329BU, 0x9A2CEF74U, 0x620FA201U,
  0x3AC346ABU, 0x0A03200AU, 0x9654238CU, 0xB2D7021DU, 0x3AA317C0U, 0x9BFBAE08U,
  0x82060BE2U, 0x6C6B5D93U, 0xA74CB2FDU, 0xC6E9CDE1U, 0xA7301C40U, 0x3736EE87U,
  0x7F0B2B3EU, 0x09FEB968U, 0xAF59EDB5U, 0xAE8DA2EFU, 0xE385A76AU, 0x9315B99AU,
  0x91931112U, 0xC010A4C6U, 0x4BDF7046U, 0xB6D37EFFU, 0x7DF625E2U, 0x9DD3FD1DU,
  0xD9128B25U, 0x80B4B88CU, 0xDAE260C7U, 0x9D62E132U, 0xBA7AAF29U, 0x3F6FFEF4U,
  0x1FF92052U, 0x824F39A8U, 0xA5C8DCD3U, 0x4F519DB6U, 0xFD0D6584U, 0x00637165U,
  0xD4F4BEDAU, 0xCA6DFB0FU, 0x2CEA4771U, 0x9E7ECE4CU, 0x2B8CBD8FU, 0x89DF259DU,
  0x30E2E9BEU, 0x83BA715CU, 0x0A3D3996U, 0x7869D9F7U, 0x9918770EU, 0x2612E0C3U,
  0xEB7DFB56U, 0x5B3773A9U, 0x908AA302U, 0x2C6F510EU, 0x44106E8FU, 0x6A33B2C7U,
  0x5552B145U, 0x784DCB13U, 0x2E930DD1U, 0x038BC6D4U, 0xA464137EU, 0x671F25B4U,
  0xEA5D593DU, 0xDF9FDA16U, 0x615EC5C1U, 0x91434E75U, 0x0D2F8E88U, 0xEC7A2F76U,
  0xEB105BD5U, 0x3EB92169U, 0x1A25EA55U, 0x660D67F2U, 0x7F7ACE42U, 0xAF2DB8C2U,
  0x87082690U, 0x3D74C23EU, 0x27CB9A48U, 0x7B8263E9U, 0xE3A80D33U, 0x3D6B7310U,
  0xAD756653U, 0x316AADC9U, 0x5EDB32C6U, 0x8120C979U, 0x6CC42D03U, 0x2A252750U,
  0xE506F194U, 0xFA3BAAB8U, 0x215B270BU, 0xE4D987B4U, 0x6F11F874U, 0x8BAF7F17U,
  0xF0222453U, 0x49E3C917U, 0x63B13067U, 0x690732E9U, 0x375E81C8U, 0x2A08643BU,
  0xFD557009U, 0xEBBD4BFFU, 0xFC273FD6U, 0xBEC86AA3U, 0xB12D323DU, 0xBEFB702DU,
  0x7AB63752U, 0xFB8A651AU, 0xEBBE1CEBU, 0x7BCA5204U, 0xBE716C84U, 0x7651FDB3U,
  0xB36324A2U, 0x22941DDFU, 0xEE2C1EF2U, 0x032BFB0BU, 0x92C8A363U, 0x4AD1385DU,
  0x72315F0FU, 0x7133A9B7U, 0xFC50E66DU, 0x115C0E7BU, 0x92DC04D2U, 0x700B8143U,
  0x0B75BEACU, 0xF94CBBC3U, 0xEC4B75CFU, 0x68B8B81BU, 0x8143A1DDU, 0x358A0A41U,
  0x80062445U, 0xA6B34A73U, 0xD67D6CBAU, 0xEE09B97BU, 0x51027F5FU, 0xFFB25A11U,
  0x03268B7BU, 0xA08053B0U, 0xFBC63695U, 0x2281FBF3U, 0x35FBBB56U, 0x671FDC85U,
  0xE9E62C59U, 0xF47EC77FU, 0x1D1ADB92U, 0x70C64534U, 0xBFB984E4U, 0x5767F4DAU,
  0x68E2553BU, 0x1339BBA6U, 0xAC733422U, 0xEC5E515AU, 0x4BCBBD86U, 0xBD2A2FD0U,
  0x6DC4837CU, 0x8E720DA1U, 0xEC8B197BU, 0xAB84914CU, 0x45960660U, 0x88062651U,
  0x9FE8FB14U, 0x5FF67CA5U, 0x22603EFFU, 0xED5C82EFU, 0x75242D36U, 0x068573D1U,
  0x7B85DB11U, 0x1DCA6360U, 0x698224ACU, 0xB7DA0A59U, 0xBB9AB9F1U, 0x9015B653U,
  0x37CD7017U, 0xEBF11283U, 0xDD3BB21EU, 0xE3515E08U, 0x38B7CC20U, 0x87BBEB57U,
  0x75CBA25CU, 0xF513DF82U, 0xB511F127U, 0x6623D584U, 0x4B4BD5E3U, 0x06DECAE6U,
  0x1F152D55U, 0xE68FEA0FU, 0x426497CDU, 0xD658ACCBU, 0x73B776F9U, 0x0070952DU,
  0x0975A93DU, 0x0D6F0757U, 0x0FFC6AADU, 0x2DB08257U, 0xE65498EAU, 0x894DE9A2U,
  0x5534FA71U, 0x1943A79DU, 0xF7313933U, 0x2AD48C6CU, 0x698BD25BU, 0xFA35A98FU,
  0xA4C3A0A2U, 0x9CAB95F3U, 0xC6BB3807U, 0x3995E96AU, 0x2D12CA48U, 0x266A3FE2U,
  0x7DCB8409U, 0x8C29E7B5U, 0xB3663806U, 0xF688D7B5U, 0xD7688256U, 0x425209F1U,
  0xFCFD787DU, 0x163E2A1BU, 0x9D2E3767U, 0xCD654CC6U, 0xFE47B980U, 0x316D9D79U,
  0x9EF4B7A3U, 0x2D33F923U, 0xB388E645U, 0x76DABC28U, 0x40829AE4U, 0xD4BA0E83U,
  0x3C126AEBU, 0x9D6A514AU, 0x9B21F5EEU, 0x74D10263U, 0x967BEFBEU, 0xAC1F8D6FU,
  0xA5D24895U, 0xF95111C2U, 0xB1229C6CU, 0xC17E6AF1U, 0x8C4907DEU, 0x6B2087F1U,
  0xF66BBB18U, 0x7BF9C7E4U, 0xB7E3B3E4U, 0xB44C7704U, 0x37957D4CU, 0x25EC41FFU,
  0xC39FEB46U, 0x8818975DU, 0x438032CCU, 0x31E15F8EU, 0x01DFBAA3U, 0x008B999CU,
  0x059C3673U, 0x61FCB399U, 0xE83CCAAFU, 0x5D6D4941U, 0xA8D82514U, 0xDA3F6C56U,
  0x11F31256U, 0x855E48F5U, 0x624876C9U, 0x7903B1C9U, 0x1DFE2E59U, 0xC7FCFBB3U,
  0x48F347BCU, 0x970672DAU, 0x435DE6E1U, 0xD9247120U, 0x8C62A8DBU, 0xD80E4165U,
  0x86856CFFU, 0xC8175CCDU, 0x8A5C07ADU, 0xE44510EAU, 0x88EBCCB2U, 0xD0051D5AU,
  0xD7D26714U, 0xDA00CEE1U, 0x60D6B57DU, 0x4609D58AU, 0x7BE3D5BDU, 0x0E706876U,
  0x988519D8U, 0x374045ABU, 0x68B59C9AU, 0x59994341U, 0xA376071AU, 0x82790598U,
  0x0C1803B9U, 0xB6AE61F9U, 0x00378FD8U, 0xDA191F2DU, 0xE524C884U, 0x585EF890U,
  0x504F4D54U, 0xE2B1B845U, 0x9BACE098U, 0xB1837C56U, 0x1AB304ADU, 0xD4F058F8U,
  0xB5BE0568U, 0x9286EFFAU, 0x257B92A6U, 0xA2921F85U, 0xD523A4DBU, 0x296B4621U,
  0x551930F2U, 0x7224056FU, 0x0D3F4D71U, 0x111882CCU, 0xF2EC9306U, 0xD193208BU,
  0x7EF861C8U, 0xE7C2F73DU, 0x71851413U, 0x5932C967U, 0x551801DBU, 0x7F0D117CU,
  0xD6B21612U, 0x7022ED50U, 0xC2CEDFE1U, 0xB52F2AB4U, 0xEAC2BBDEU, 0xA1F20C77U,
  0x131A87C2U, 0x3CF11880U, 0xB0556DD0U, 0xFD7A69D4U, 0x3E936427U, 0x287DD483U,
  0xB6E2EA0AU, 0xFE36092BU, 0xE47EC84BU, 0xEA2BBD62U, 0xEDC1141EU, 0xC25CC47DU,
  0x3499C101U, 0x8256A60CU, 0x2318A272U, 0x63B8EC33U, 0x300653D5U, 0xAC0A5695U,
  0x6680CD03U, 0xD4432796U, 0x6E7AECD6U, 0xBDA51891U, 0xA5240444U, 0x262E3603U,
  0x5C76D10BU, 0x9ED4A2DAU, 0xE7EB24ABU, 0x7B3E547CU, 0x1028478BU, 0x897D80F1U,
  0x76C857B4U, 0xE8E2BFB1U, 0x4D7A7923U, 0x3DE4E3DDU, 0xA296D0BEU, 0x66B49B35U,
  0xD8F53948U, 0x205EE340U, 0xE39ED79BU, 0xAC9E8524U, 0x7D917769U, 0x12685186U,
  0xE94469F0U, 0x488186A2U, 0x9AF753ABU, 0xF1F92D7DU, 0xF8BE38BAU, 0xC4D70BE7U,
  0x291DC98FU, 0x8EF6E653U, 0x2BF08A59U, 0x9797DC97U, 0xDB93A690U, 0xE2B9D8DEU,
  0x107B8575U, 0x940397E0U, 0x3D61B058U, 0xE0D4AC11U, 0x2FFBC5DEU, 0xDDB57A97U,
  0xD6517F82U, 0x8A4D5FF4U, 0xD81F4EABU, 0x74F462C0U, 0x08426732U, 0xECF00504U,
  0x27165F49U, 0xC242ADEEU, 0x17E6D61FU, 0x1F5786C4U, 0xD9C10D38U, 0xE2339EA6U,
  0xBC18C2D8U, 0xE0D09238U, 0x29C0E9AEU, 0x130EC864U, 0xD43A3E9FU, 0x0B665374U,
  0x8EEC5382U, 0x838132D0U, 0x39B4377EU, 0x376A64C1U, 0x41A01358U, 0x5BB0209FU,
  0x3944C44CU, 0x7607FE03U, 0x33F359DFU, 0xC6F1C60EU, 0x98CED064U, 0x990B6925U,
  0x7E4A8307U, 0xB4FCCD4FU, 0x9A39DBD2U, 0xFB210653U, 0xD1703002U, 0x699A6817U,
  0xAF99A33DU, 0x230CE794U, 0x3CF0F9BCU, 0x69022CFBU, 0x39C74348U, 0x7569A3E1U,
  0x73687EE0U, 0x9DA9AF06U, 0x28BDB3DEU, 0xE2A35E54U, 0xD297398CU, 0x7791EF85U,
  0x95CFAC2DU, 0x23C18F12U, 0x0C4C3A91U, 0xF1D3B6E4U, 0xCBDC3392U, 0x771C1681U,
  0x1DC361A0U, 0x8F75A67DU, 0x03E1F577U, 0x7E2F7485U, 0xE2D7CE64U, 0x0BCF90D8U,
  0x499FFE54U, 0x4EC3A519U, 0xD0FE959FU, 0x6F278CF0U, 0xB79C555EU, 0x3F81248CU,
  0x29EF6F2EU, 0x2805840CU, 0x5352A3D1U, 0xA3D4D5FBU, 0xE7A41A03U, 0x83D90B92U,
  0x575630A8U, 0xCBB6DFD3U, 0x27EBB84FU, 0x0D101007U, 0x2D15FF81U, 0xFA2307A1U,
  0x6BE6C18FU, 0x16B2D955U, 0xFBD44C28U, 0x1176D8A9U, 0xAD7FFA21U, 0x9E6CAAC9U,
  0xB626A638U, 0xD140FB79U, 0xF4E2171AU, 0x63F04CFDU, 0xB32D4A5BU, 0x5C125339U,
  0x24DBAE21U, 0x37A6D22FU, 0x217F6C48U, 0x9354E53BU, 0x00000000U, 0x00000000U,
  };
  unsigned int i;
  
  do {
    if( DT_E_NOERR != ( err = hc256_new( &cipher ) ) ) break;
    if( DT_E_NOERR != ( err = hc256_iv( cipher, iv ) ) ) break;
    if( DT_E_NOERR != ( err = hc256_key( cipher, key ) ) ) break;
    err = hc256_init( cipher );
    CU_ASSERT_EQUAL( DT_E_NOERR, err );
    if( DT_E_NOERR != err ) break;
    data = (unsigned int *) cipher;

    for( i = 0; i < ( sizeof( hc256 ) / 4 ); i++ ) {
      if( expected[i] != data[i] ) break;
    }

    if( ( sizeof( hc256 ) / 4 ) == i ) {
      CU_PASS("hc256_init() works.");
    } else {
      CU_FAIL("hc256_init() is having problems.");
    }
  } while( 0 );
}

void hc256_test_initf_null_cipher( void ) {
  CU_ASSERT_EQUAL( DT_E_NULL, hc256_init( NULL ) );
}

void hc256_test_keystream( void ) {
  DTErr err = DT_E_NOERR;
  char *output = NULL;
  unsigned int bytes_written = 0;
  int compare = 0;
  
  static char key[] = {
    0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };
  
  static char iv[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };
  
  static char expected[] = {
    0xfe, 0x4a, 0x40, 0x1c, 0xed, 0x5f, 0xe2, 0x4f,
    0xd1, 0x9a, 0x8f, 0x95, 0x6f, 0xc0, 0x36, 0xae,
    0x3c, 0x5a, 0xa6, 0x88, 0x23, 0xe2, 0xab, 0xc0,
    0x2f, 0x90, 0xb3, 0xae, 0xa8, 0xd3, 0x0e, 0x42,
    0x59, 0xf0, 0x3a, 0x6c, 0x6e, 0x39, 0xeb, 0x44,
    0x8f, 0x75, 0x79, 0xfb, 0x70, 0x13, 0x7a, 0x5e,
    0x6d, 0x10, 0xb7, 0xd8, 0xad, 0xd0, 0xf7, 0xcd,
    0x72, 0x34, 0x23, 0xda, 0xf5, 0x75, 0xdd, 0xe6,
  };
  
  do {
    if( NULL == ( output = malloc( 64 ) ) ) {
      break;
    }
    
    err = hc256_clear( cipher );
    CU_ASSERT( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }
    
    err = hc256_key( cipher, key );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_iv( cipher, iv );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_init( cipher );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_keystream( cipher, output, 64, &bytes_written );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_clear( cipher );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    CU_ASSERT_TRUE( 64 == bytes_written );
    if( 64 != bytes_written ) {
      break;
    }

    compare = memcmp( output, expected, 64 );
    CU_ASSERT_TRUE( 0 == compare );
    if( 0 != compare ) {
      CU_PASS( "hc256_keystream() failed" );
      break;
    }

    CU_PASS( "hc256_keystream() passed" );
  } while( 0 );

  if( NULL != output ) {
    free( output );
  }
}

void hc256_test_keystream_null_cipher_output_bytes ( void ) {
  char buffer[64];
  unsigned int b;
  CU_ASSERT_EQUAL( DT_E_NULL, hc256_keystream( NULL, NULL, 64, NULL ) );
}

void hc256_test_keystream_null_cipher_output( void ) {
  char buffer[64];
  unsigned int b;
  CU_ASSERT_EQUAL( DT_E_NULL, hc256_keystream( NULL, NULL, 64, &b ) );
}

void hc256_test_keystream_null_cipher_bytes( void ) {
  char buffer[64];
  CU_ASSERT_EQUAL( DT_E_NULL, hc256_keystream( NULL, buffer, 64, NULL ) );
}

void hc256_test_keystream_null_cipher( void ) {
  char buffer[64];
  unsigned int b;
  CU_ASSERT_EQUAL( DT_E_NULL, hc256_keystream( NULL, buffer, 64, &b ) );
}

void hc256_test_keystream_null_output_bytes( void ) {
  hc256 *cipher = NULL;
  DTErr err;

  do {
    err = hc256_new( &cipher );
    CU_ASSERT_EQUAL( DT_E_NOERR, err );
    if( DT_E_NOERR != err ) break;

    CU_ASSERT_EQUAL( DT_E_NULL, hc256_keystream( cipher, NULL, 64, NULL ) );

    hc256_delete( cipher );
  } while( 0 );
}

void hc256_test_keystream_null_output( void ) {
  hc256 *cipher = NULL;
  DTErr err;
  unsigned int b;

  do {
    err = hc256_new( &cipher );
    CU_ASSERT_EQUAL( DT_E_NOERR, err );
    if( DT_E_NOERR != err ) break;

    CU_ASSERT_EQUAL( DT_E_NULL, hc256_keystream( cipher, NULL, 64, &b ) );

    hc256_delete( cipher );
  } while( 0 );
}

void hc256_test_keystream_null_bytes( void ) {
  DTErr err = DT_E_NOERR;
  char *output = NULL;
  int compare = 0;

  static char key[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };

  static char iv[] = {
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };

  static char expected[] = {
    0xbf, 0xa2, 0xe2, 0xaf, 0xe9, 0xce, 0x17, 0x4f,
    0x8b, 0x05, 0xc2, 0xfe, 0xb1, 0x8b, 0xb1, 0xd1,
    0xee, 0x42, 0xc0, 0x5f, 0x01, 0x31, 0x2b, 0x71,
    0xc6, 0x1f, 0x50, 0xdd, 0x50, 0x2a, 0x08, 0x0b,
    0xed, 0xfe, 0xc7, 0x06, 0x63, 0x3d, 0x92, 0x41,
    0xa6, 0xda, 0xc4, 0x48, 0xaf, 0x85, 0x61, 0xff,
    0x5e, 0x04, 0x13, 0x5a, 0x94, 0x48, 0xc4, 0x34,
    0x2d, 0xe7, 0xe9, 0xf3, 0x37, 0x52, 0x0b, 0xdf
  };

  do {
    if( NULL == ( output = malloc( 64 ) ) ) {
      break;
    }

    err = hc256_clear( cipher );
    CU_ASSERT( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_key( cipher, key );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_iv( cipher, iv );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_init( cipher );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_keystream( cipher, output, 64, NULL);
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_clear( cipher );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    compare = memcmp( output, expected, 64 );
    CU_ASSERT_TRUE( 0 == compare );
    if( 0 != compare ) {
      break;
    }

    CU_PASS( "calling hc256_keystream() with a null bytes_written parameter is okay." );
  } while( 0 );

  if( NULL != output ) {
    free( output );
  }
}

void hc256_test_keystream_zero_length( void ) {
  DTErr err = DT_E_NOERR;
  char *output = NULL;
  int compare = 0;
  unsigned int bytes_written = 64;

  static char key[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };

  static char iv[] = {
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };

  static char expected[] = {
    0xbf, 0xa2, 0xe2, 0xaf, 0xe9, 0xce, 0x17, 0x4f,
    0x8b, 0x05, 0xc2, 0xfe, 0xb1, 0x8b, 0xb1, 0xd1,
    0xee, 0x42, 0xc0, 0x5f, 0x01, 0x31, 0x2b, 0x71,
    0xc6, 0x1f, 0x50, 0xdd, 0x50, 0x2a, 0x08, 0x0b,
    0xed, 0xfe, 0xc7, 0x06, 0x63, 0x3d, 0x92, 0x41,
    0xa6, 0xda, 0xc4, 0x48, 0xaf, 0x85, 0x61, 0xff,
    0x5e, 0x04, 0x13, 0x5a, 0x94, 0x48, 0xc4, 0x34,
    0x2d, 0xe7, 0xe9, 0xf3, 0x37, 0x52, 0x0b, 0xdf
  };

  do {
    if( NULL == ( output = malloc( 64 ) ) ) {
      break;
    }

    err = hc256_clear( cipher );
    CU_ASSERT( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_key( cipher, key );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_iv( cipher, iv );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_init( cipher );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_keystream( cipher, output, 0, &bytes_written);
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    if( bytes_written != 0 ) {
      CU_FAIL("calling hc256_keystream() with zero length has problems.");
      break;
    }

    err = hc256_clear( cipher );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    compare = memcmp( output, expected, 64 );
    CU_ASSERT_TRUE( 0 == compare );
    if( 0 != compare ) {
      break;
    }

    CU_PASS( "calling hc256_keystream() with zero length is okay." );
  } while( 0 );

  if( NULL != output ) {
    free( output );
  }
}

void hc256_test_keystream_zero_length_null_bytes( void ) {
  DTErr err = DT_E_NOERR;
  char *output = NULL;
  int compare = 0;

  static char key[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };

  static char iv[] = {
    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };

  static char expected[] = {
    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
  };

  do {
    if( NULL == ( output = malloc( 64 ) ) ) {
      break;
    }
    
    memset( output, 0xAA, 64 );

    err = hc256_clear( cipher );
    CU_ASSERT( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_key( cipher, key );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_iv( cipher, iv );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_init( cipher );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_keystream( cipher, output, 0, NULL);
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_clear( cipher );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    compare = memcmp( output, expected, 64 );
    CU_ASSERT_TRUE( 0 == compare );
    if( 0 != compare ) {
      break;
    }

    CU_PASS( "calling hc256_keystream() with zero length is okay." );
  } while( 0 );

  if( NULL != output ) {
    free( output );
  }
}

void hc256_test_encrypt( void ) {
  DTErr err = DT_E_NOERR;
  char *output = NULL;
  unsigned int bytes_written = 0;
  int compare = 0;

  static char key[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };

  static char iv[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };

  static char input[] = {
    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
    0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00,
    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
    0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00,
    0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
    0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0xF0,
    0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
    0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF, 0xF0,
  };
  
  static char expected[] = {
    0x84, 0x8B, 0x04, 0x5F, 0x08, 0xF5, 0xF1, 0xD0,
    0x26, 0xCA, 0xCE, 0x4E, 0x5C, 0x77, 0xB9, 0xA6,
    0x35, 0x67, 0xF3, 0x57, 0xF7, 0x8F, 0x18, 0x88,
    0x82, 0x2E, 0x7F, 0x42, 0x15, 0x46, 0x04, 0x72,
    0x1D, 0xD5, 0x61, 0x39, 0x4A, 0xBB, 0x38, 0x13,
    0x8E, 0x93, 0x44, 0x71, 0x07, 0xEA, 0x51, 0x14,
    0x8A, 0xBE, 0xA3, 0x1C, 0x1F, 0x05, 0x5E, 0x30,
    0x0C, 0xFC, 0xFA, 0x90, 0x7C, 0x97, 0x81, 0xC2
  };

  do {
    if( NULL == ( output = malloc( 64 ) ) ) {
      break;
    }

    err = hc256_clear( cipher );
    CU_ASSERT( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_key( cipher, key );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_iv( cipher, iv );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_init( cipher );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    err = hc256_encrypt( cipher, input, 64, output, 64, &bytes_written );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    CU_ASSERT_TRUE( 64 == bytes_written );
    if( 64 != bytes_written ) break;

    err = hc256_clear( cipher );
    CU_ASSERT_TRUE( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) {
      break;
    }

    CU_ASSERT_TRUE( 64 == bytes_written );
    if( 64 != bytes_written ) {
      break;
    }

    compare = memcmp( output, expected, 64 );
    CU_ASSERT_TRUE( 0 == compare );
    if( 0 != compare ) {
      CU_FAIL( "hc256_encrypt() had some problems." );
      break;
    }

    CU_PASS( "hc256_encrypt() seems to work." );
  } while( 0 );

  if( NULL != output ) {
    free( output );
  }
}

void hc256_test_encrypt_null_cipher( void ) {
  char in[64], out[64];
  unsigned int b;

  CU_ASSERT_EQUAL( DT_E_NULL, hc256_encrypt( NULL, in, 64, out, 64, &b ) );
}

void hc256_test_encrypt_null_input( void ) {
  char in[64], out[64];
  unsigned int b;
  hc256 *cipher = NULL;
  DTErr err;

  do {
    err = hc256_new( &cipher );
    CU_ASSERT_EQUAL( DT_E_NOERR, err );
    if( DT_E_NOERR != err ) break;

    err = hc256_init( cipher );
    CU_ASSERT_EQUAL( DT_E_NOERR, err );
    if( DT_E_NOERR != err ) break;

    CU_ASSERT_EQUAL( DT_E_NULL, hc256_encrypt(cipher,NULL, 64, out, 64, &b ) );
  } while( 0 );

  if( NULL != cipher ) {
    hc256_delete( cipher );
  }
}

void hc256_test_encrypt_null_output( void ) {
  char in[64], out[64];
  unsigned int b;
  hc256 *cipher = NULL;
  DTErr err;

  do {
    err = hc256_new( &cipher );
    CU_ASSERT_EQUAL( DT_E_NOERR, err );
    if( DT_E_NOERR != err ) break;

    err = hc256_init( cipher );
    CU_ASSERT_EQUAL( DT_E_NOERR, err );
    if( DT_E_NOERR != err ) break;

    CU_ASSERT_EQUAL( DT_E_NULL, hc256_encrypt(cipher,in, 64,NULL, 64, &b ) );
  } while( 0 );

  if( NULL != cipher ) {
    hc256_delete( cipher );
  }
}

void hc256_test_encrypt_null_bytes( void ) {
  CU_FAIL( "Unimplemented" );
}

void hc256_test_encrypt_zero_input_length( void ) {
  CU_FAIL( "Unimplemented" );
}

void hc256_test_encrypt_zero_output_length( void ) {
  CU_FAIL( "Unimplemented" );
}

void hc256_test_decrypt( void ) {
  CU_FAIL( "Unimplemented" );
}

void hc256_test_absolute_forward( void ) {
  CU_FAIL( "Unimplemented" );
}

void hc256_test_absolute_backward( void ) {
  CU_FAIL( "Unimplemented" );
}

void hc256_test_relative_forward( void ) {
  CU_FAIL( "Unimplemented" );
}

void hc256_test_relative_backward( void ) {
  CU_FAIL( "Unimplemented" );
}

void hc256_test_seek_null_cipher( void ) {
  CU_ASSERT_EQUAL( DT_E_NULL, hc256_seek( NULL, DT_SEEK_ABSOLUTE, 16 ) );
}

void hc256_test_seek_invalid_mode( void ) {
  char in[64], out[64];
  unsigned int b;
  hc256 *cipher = NULL;
  DTErr err;

  do {
    err = hc256_new( &cipher );
    CU_ASSERT_EQUAL( DT_E_NOERR, err );
    if( DT_E_NOERR != err ) break;

    err = hc256_init( cipher );
    CU_ASSERT_EQUAL( DT_E_NOERR, err );
    if( DT_E_NOERR != err ) break;

    CU_ASSERT_EQUAL( DT_E_BADPARAMS, hc256_seek( cipher, 2, 16 ) );

  } while( 0 );

  if( NULL != cipher ) {
    hc256_delete( cipher );
  }
}

void hc256_test_seek_negative_absolute( void ) {
  char in[64], out[64];
  unsigned int b;
  hc256 *cipher = NULL;
  DTErr err;

  do {
    err = hc256_new( &cipher );
    CU_ASSERT_EQUAL( DT_E_NOERR, err );
    if( DT_E_NOERR != err ) break;

    err = hc256_init( cipher );
    CU_ASSERT_EQUAL( DT_E_NOERR, err );
    if( DT_E_NOERR != err ) break;

    CU_ASSERT_EQUAL( DT_E_BADPARAMS, hc256_seek( cipher, DT_SEEK_ABSOLUTE, -1 ) );

  } while( 0 );

  if( NULL != cipher ) {
    hc256_delete( cipher );
  }
}

void hc256_test_clear( void ) {
  DTErr err = DT_E_NOERR;
  char output[64];
  unsigned int i;
  int compare = 1;
  hc256 *cipher = NULL;
  char *data;

  static char key[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };

  static char iv[] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  };

  do {
    if( DT_E_NOERR != ( err = hc256_new( &cipher ) ) ) break;
    if( DT_E_NOERR != ( err = hc256_key( cipher, key ) ) ) break;
    if( DT_E_NOERR != ( err = hc256_iv( cipher, iv ) ) ) break;
    if( DT_E_NOERR != ( err = hc256_init( cipher ) ) ) break;

    err = hc256_clear( cipher );
    CU_ASSERT( DT_E_NOERR == err );
    if( DT_E_NOERR != err ) break;

    data = (char *) cipher;

    for( i = 0; i < sizeof( hc256 ); i++ ) {
      if( 0 != data[i] ) break;
    }

    if( sizeof( hc256 ) == i ) {
      compare = 0;
    }

  } while( 0 );

  if( NULL != cipher ) {
    hc256_delete( cipher );
  }

  if( 0 == compare ) {
    CU_PASS( "hc256_clear() seems to be working." );
  } else {
    CU_FAIL( "hc256_clear() seems not to be working.");
  }
}

void hc256_test_delete( void ) {
  CU_FAIL( "Unimplemented" );
}

/* This test mirrors the vector 1 test above, but it calls the hc256_lower
** functions directly. Note that we're using 32 bit integers as input and
** output instead of char arrays. The lower layer does no memory
** management (it assumes that everything is pre-allocated) and it returns
** no errors from the init and keystream calls.
*/
void hc256_test_lower1( void ) {
  uint32_t i;
  uint32_t b;

  /* setup keys, ivs and expected outputs */
  static uint32_t key[8] = {
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U
  };

  static uint32_t iv[8] = {
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U
  };

  static uint32_t expected[16] = {
    0x8589075BU,
    0x0DF3F6D8U,
    0x2FC0C542U,
    0x5179B6A6U, 
    0x3465F053U,
    0xF2891F80U,
    0x8B24744EU,
    0x18480B72U, 
    0xEC2792CDU,
    0xBF4DCFEBU,
    0x7769BF8DU,
    0xFA14AEE4U,
    0x7B4C50E8U,
    0xEAF3A9C8U,
    0xF506016CU,
    0x81697E32U
  };


  uint32_t actual[16];
  uint32_t w[2560];
  hc256 context;
  unsigned int bytes_written;

  /* clear the context and the space for the actual results */
  memset( actual, 0, 64 );
  memset( & context, 0, sizeof( hc256 ) );

  /* copy the key and iv into the context */
  memcpy( context.key, key, 32 );
  memcpy( context.iv, iv, 32 );

  /* now initialize */
  hc256_lower_init( &context, w );

  /* check to see if we initialized properly */

  /* now generate some keystream */
  hc256_lower_keystream( &context, actual, 64, &bytes_written );

  /* now check to see if we got the right output */
  b = 0;
  for( i = 0; i < 16; i++ ) {
    if( actual[i] != expected[i] ) {
      b = 1;
      break;
    }
  }
  if( 0 == b ) {
    CU_PASS( "lower vector 1 generated correct results" );
  } else {
    CU_FAIL( "lower vector 1 did not generated correct results" );
  }
}

void hc256_test_lower2( void ) {
  uint32_t i;
  uint32_t b;

  /* setup keys, ivs and expected outputs */
  static uint32_t key[8] = {
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U
  };

  static uint32_t iv[8] = {
    0x00000001U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U
  };

  static uint32_t expected[16] = {
    0xBFA2E2AFU,
    0xE9CE174FU,
    0x8B05C2FEU,
    0xB18BB1D1U,
    0xEE42C05FU,
    0x01312B71U,
    0xC61F50DDU,
    0x502A080BU,
    0xEDFEC706U,
    0x633D9241U,
    0xA6DAC448U,
    0xAF8561FFU,
    0x5E04135AU,
    0x9448C434U,
    0x2DE7E9F3U,
    0x37520BDFU
  };


  uint32_t actual[16];
  uint32_t w[2560];
  hc256 context;
  unsigned int bytes_written;

  /* clear the context and the space for the actual results */
  memset( actual, 0, 64 );
  memset( & context, 0, sizeof( hc256 ) );

  /* copy the key and iv into the context */
  memcpy( context.key, key, 32 );
  memcpy( context.iv, iv, 32 );

  /* now initialize */
  hc256_lower_init( &context, w );

  /* check to see if we initialized properly */

  /* now generate some keystream */
  hc256_lower_keystream( &context, actual, 64, &bytes_written );

  /* now check to see if we got the right output */
  b = 0;
  for( i = 0; i < 16; i++ ) {
    if( actual[i] != expected[i] ) {
      b = 1;
      break;
    }
  }
  if( 0 == b ) {
    CU_PASS( "lower vector 1 generated correct results" );
  } else {
    CU_FAIL( "lower vector 1 did not generated correct results" );
  }
}

void hc256_test_lower3( void ) {
  uint32_t i;
  uint32_t b;

  /* setup keys, ivs and expected outputs */
  static uint32_t key[8] = {
    0x00000055U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U
  };

  static uint32_t iv[8] = {
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U
  };

  static uint32_t expected[16] = {
    0xFE4A401CU,
    0xED5FE24FU,
    0xD19A8F95U,
    0x6FC036AEU,
    0x3C5AA688U,
    0x23E2ABC0U,
    0x2F90B3AEU,
    0xA8D30E42U,
    0x59F03A6CU,
    0x6E39EB44U,
    0x8F7579FBU,
    0x70137A5EU,
    0x6D10B7D8U,
    0xADD0F7CDU,
    0x723423DAU,
    0xF575DDE6U
  };


  uint32_t actual[16];
  uint32_t w[2560];
  hc256 context;
  unsigned int bytes_written;

  /* clear the context and the space for the actual results */
  memset( actual, 0, 64 );
  memset( & context, 0, sizeof( hc256 ) );

  /* copy the key and iv into the context */
  memcpy( context.key, key, 32 );
  memcpy( context.iv, iv, 32 );

  /* now initialize */
  hc256_lower_init( &context, w );

  /* check to see if we initialized properly */

  /* now generate some keystream */
  hc256_lower_keystream( &context, actual, 64, &bytes_written );

  /* now check to see if we got the right output */
  b = 0;
  for( i = 0; i < 16; i++ ) {
    if( actual[i] != expected[i] ) {
      b = 1;
      break;
    }
  }
  if( 0 == b ) {
    CU_PASS( "lower vector 1 generated correct results" );
  } else {
    CU_FAIL( "lower vector 1 did not generated correct results" );
  }
}

void hc256_test_lower4( void ) {

  uint32_t i,j;
  uint32_t b;

  /* setup keys, ivs and expected outputs */
  static uint32_t key[8] = {
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U
  };

  static uint32_t iv[8] = {
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U,
    0x00000000U
  };

  static uint32_t expected[16] = {
    0xC6B6FB99U,
    0xF2AE1440U,
    0xA7D4CA34U,
    0x2011694EU,
    0x6F36B4BEU,
    0x420DB05DU,
    0x4745FD90U,
    0x7C630695U,
    0x5F1D7BDAU,
    0x13AE7E36U,
    0xAEBC5399U,
    0x733B7F37U,
    0x95F34066U,
    0xB601D21FU,
    0x2D8CF830U,
    0xA9C08937U
  };


  uint32_t actual0[16];
  uint32_t actual1[16];
  uint32_t *actual;
  uint32_t w[2560];
  hc256 context;
  unsigned int bytes_written;

  /* clear the context and the space for the actual results */
  memset( actual0, 0, 64 );
  memset( actual1, 0, 64 );
  memset( & context, 0, sizeof( hc256 ) );

  /* copy the key and iv into the context */
  memcpy( context.key, key, 32 );
  memcpy( context.iv, iv, 32 );

  /* now initialize */
  hc256_lower_init( &context, w );

  for( i = 0; i < 0x10000; i++ ) {
    if( 0 == ( i & 1 ) ) {
      actual = actual0;
    } else {
      actual = actual1;
    }

    hc256_lower_keystream( &context, actual, 64, &bytes_written );
    
    if( 0 == ( i & 1 ) ) {
      for( j = 0; j< 16; j++ ) {
	actual0[ j ] = actual0[ j ] ^ actual1[ j ];
      }
    } else {
      for( j = 0; j< 16; j++ ) {
	actual1[ j ] = actual0[ j ] ^ actual1[ j ];
      }
    } 
  }

  /* now check to see if we got the right output */
  b = 0;
  for( i = 0; i < 16; i++ ) {
    if( actual[i] != expected[i] ) {
      b = 1;
      break;
    }
  }
  if( 0 == b ) {
    CU_PASS( "lower vector 1 generated correct results" );
  } else {
    CU_FAIL( "lower vector 1 did not generated correct results" );
  }
}

